import pygame
import random
import math
from typing import Optional

# ======== 墙体系统 ========
class Wall:  # 墙体类
    def __init__(self, x, y, wall_type=1, cell_size=36):  # 构造函数，wall_type: 0=石墙, 1=木箱, 2=草丛
        self.x = x  # x坐标
        self.y = y  # y坐标
        self.width = cell_size  # 墙体宽度
        self.height = cell_size  # 墙体高度
        self.rect = pygame.Rect(x, y, self.width, self.height)  # 墙体矩形
        self.alive = True  # 是否存活
        self.wall_type = wall_type  # 墙体类型
        self.hit_count = 0  # 被击中次数
        self.max_hits = 3 if wall_type == 1 else 999 if wall_type == 0 else 0  # 最大承受攻击次数

    def draw(self, surface, camera_x=0, camera_y=0):
        if not self.alive:  # 如果墙体被摧毁，直接不绘制
            return
            
        # 转换坐标到屏幕坐标
        screen_x = self.x - camera_x
        screen_y = self.y - camera_y
        
        # 只绘制在可视区域内的墙体
        if -self.width <= screen_x <= 864 and -self.height <= screen_y <= 864:
            screen_rect = pygame.Rect(screen_x, screen_y, self.width, self.height)
            
            if self.wall_type == 0:  # 石墙
                color = (80, 80, 80)  # 深灰色
                pygame.draw.rect(surface, color, screen_rect)
                # 添加石墙纹理效果
                pygame.draw.line(surface, (60, 60, 60), (screen_x, screen_y), (screen_x + self.width, screen_y), 2)
                pygame.draw.line(surface, (60, 60, 60), (screen_x, screen_y), (screen_x, screen_y + self.height), 2)
                
            elif self.wall_type == 1:  # 木箱
                # 绘制木箱主体
                color = (139, 69, 19)  # 深棕色
                pygame.draw.rect(surface, color, screen_rect)
                
                # 绘制木箱边框
                border_color = (101, 67, 33)  # 更深的棕色作为边框
                pygame.draw.rect(surface, border_color, screen_rect, 3)
                
                # 绘制×图案，使箱子更像箱子
                x_color = (160, 82, 45)  # 浅棕色
                # 左上到右下的×
                pygame.draw.line(surface, x_color, 
                               (screen_x + 8, screen_y + 8), 
                               (screen_x + self.width - 8, screen_y + self.height - 8), 4)
                # 右上到左下的×
                pygame.draw.line(surface, x_color, 
                               (screen_x + self.width - 8, screen_y + 8), 
                               (screen_x + 8, screen_y + self.height - 8), 4)
                
                # 添加一些木纹效果
                for i in range(0, self.width, 8):
                    pygame.draw.line(surface, (160, 82, 45), 
                                   (screen_x + i, screen_y), 
                                   (screen_x + i, screen_y + self.height), 1)
                    
            elif self.wall_type == 2:  # 草丛
                color = (34, 139, 34)  # 绿色
                pygame.draw.rect(surface, color, screen_rect)
                # 添加草丛纹理效果
                for i in range(0, self.width, 6):
                    for j in range(0, self.height, 6):
                        if random.random() < 0.3:
                            pygame.draw.line(surface, (0, 100, 0), 
                                           (screen_x + i, screen_y + j), 
                                           (screen_x + i + 2, screen_y + j - 3), 1)

    def check_collision(self, rect):
        return self.rect.colliderect(rect)  # 返回是否碰撞
        
    def hit(self):  # 墙体被击中
        if self.wall_type == 0:  # 石墙不会被击破
            return False
        elif self.wall_type == 1:  # 木箱
            self.hit_count += 1
            if self.hit_count >= self.max_hits:
                self.alive = False
                return True  # 木箱被摧毁
            return False  # 木箱未被摧毁
        elif self.wall_type == 2:  # 草丛不会被击破
            return False
        return False

    def generate_item_on_destroy(self):
        """木箱被摧毁时生成道具"""
        if self.wall_type == 1 and not self.alive and random.random() < 0.3:  # 30%概率生成道具
            item_type = random.choice(['health', 'shield'])
            # 在木箱中心位置生成道具
            item_x = self.x + self.width // 2
            item_y = self.y + self.height // 2
            return Item(item_type, item_x, item_y)
        return None

# ======== 道具系统 ========
class Item:  # 道具类
    def __init__(self, item_type, x, y):
        self.type = item_type  # 'health' 或 'shield'
        self.radius = 18  # 调整道具大小为36像素直径
        self.active = True
        self.spawn_time = pygame.time.get_ticks()
        self.pulse_value = 0
        self.pulse_speed = 0.1
        self.x = x
        self.y = y

    def draw(self, surface):  # 绘制道具
        if not self.active:  # 未激活不绘制
            return

        self.pulse_value = (self.pulse_value + self.pulse_speed) % (2 * math.pi)  # 更新脉冲动画
        pulse_size = self.radius + 3 * math.sin(self.pulse_value)  # 动画半径

        if self.type == 'health':  # 爱心道具
            points = []  # 爱心点集
            for angle in range(0, 360, 10):  # 生成爱心形状
                rad = math.radians(angle)
                x = pulse_size * (math.sin(rad) ** 3)
                y = pulse_size * (math.cos(rad) - math.cos(rad*2) - math.cos(rad*3) - math.cos(rad*4)) / 3.5
                points.append((self.x + x, self.y - y))
            pygame.draw.polygon(surface, (255, 0, 0), points)  # 绘制爱心
        elif self.type == 'shield':  # 护盾道具
            pygame.draw.circle(surface, (255, 255, 150), (self.x, self.y), int(pulse_size), 3)  # 外圈
            pygame.draw.circle(surface, (255, 255, 150), (self.x, self.y), int(pulse_size) - 8, 3)  # 内圈
            pygame.draw.arc(surface, (255, 255, 150), (self.x - pulse_size, self.y - pulse_size, pulse_size * 2, pulse_size * 2), math.pi/4, 3*math.pi/4, 3)  # 弧线

    def check_collision(self, tank):  # 检查与坦克碰撞
        if not self.active:
            return False
        tank_center_x = tank.x + tank.size // 2  # 坦克中心x
        tank_center_y = tank.y + tank.size // 2  # 坦克中心y
        distance = math.sqrt((self.x - tank_center_x) ** 2 + (self.y - tank_center_y) ** 2)  # 距离
        return distance < (self.radius + tank.size // 2)  # 是否碰撞

# ======== 子弹类 ========
class Bullet:  # 子弹类
    def __init__(self, x, y, dx, dy, is_player_bullet):  # 构造函数
        self.x = x  # x坐标
        self.y = y  # y坐标
        self.dx = dx  # x方向速度
        self.dy = dy  # y方向速度
        self.size = 12  # 子弹大小调整为12像素（36px坦克的1/3）
        self.is_player_bullet = is_player_bullet  # 是否玩家子弹
        self.color = (0, 255, 0) if is_player_bullet else (255, 0, 0)  # 子弹颜色
        self.live = True  # 是否存活
        
        # 子弹距离限制相关
        self.start_x = x  # 起始x坐标
        self.start_y = y  # 起始y坐标
        self.max_distance = 8 * 36  # 最大距离8格（8 * 36像素）
        self.current_distance = 0  # 当前飞行距离
        
        # 消失动画相关
        self.fade_alpha = 255  # 透明度
        self.fade_speed = 15  # 消失速度
        self.is_fading = False  # 是否正在消失

    def move(self):  # 子弹移动
        if self.is_fading:
            return
            
        self.x += self.dx
        self.y += self.dy
        
        # 计算飞行距离
        self.current_distance = math.sqrt((self.x - self.start_x) ** 2 + (self.y - self.start_y) ** 2)
        
        # 检查是否超过最大距离
        if self.current_distance >= self.max_distance:
            self.is_fading = True

    def update_fade(self):  # 更新消失动画
        if self.is_fading:
            self.fade_alpha -= self.fade_speed
            if self.fade_alpha <= 0:
                self.live = False
                return False
        return True

    def draw(self, surface, camera_x=0, camera_y=0):  # 绘制子弹
        # 转换坐标到屏幕坐标
        screen_x = self.x - camera_x
        screen_y = self.y - camera_y
        
        if self.is_fading:
            # 创建带透明度的表面
            bullet_surface = pygame.Surface((self.size, self.size), pygame.SRCALPHA)
            # 根据透明度绘制子弹
            alpha_color = (*self.color, self.fade_alpha)
            pygame.draw.rect(bullet_surface, alpha_color, (0, 0, self.size, self.size))
            surface.blit(bullet_surface, (screen_x, screen_y))
        else:
            pygame.draw.rect(surface, self.color, (screen_x, screen_y, self.size, self.size))

    def is_out_of_bounds(self, total_map_size=64, cell_size=36):  # 判断是否出界
        return (self.x < 0 or self.x > total_map_size * cell_size or 
                self.y < 0 or self.y > total_map_size * cell_size)

    def get_rect(self):  # 获取子弹矩形
        return pygame.Rect(self.x, self.y, self.size, self.size)

# ======== 坦克类 ========
class Tank:  # 坦克类
    def __init__(self, x, y, color, is_player=False, game_state=None):  # 构造函数
        self.x = x  # x坐标
        self.y = y  # y坐标
        self.color = color  # 颜色
        self.speed = 5 if is_player else 2  # 速度
        self.size = 36  # 坦克大小调整为36像素
        self.direction = 'UP'  # 方向
        self.bullets = []  # 子弹列表
        self.is_player = is_player  # 是否玩家
        self.hit_flash = 1  # 受击闪烁
        self.live = True  # 是否存活
        self.max_health = 3 if is_player else 1  # 最大血量
        self.health = self.max_health  # 当前血量
        self.shield_time = 0  # 护盾剩余时间
        self.shield_active = False  # 护盾激活
        self.game_state = game_state  # 游戏状态
        self.in_grass = False  # 是否在草丛中
        self.stealth_mode = False  # 隐身模式

    def check_grass_collision(self):
        """检查是否在草丛中，只有一半以上在草丛中才有隐藏效果"""
        tank_rect = pygame.Rect(self.x, self.y, self.size, self.size)
        self.in_grass = False
        grass_overlap = 0  # 草丛重叠面积
        
        if self.game_state and self.game_state.walls:
            for wall in self.game_state.walls:
                if wall.wall_type == 2 and wall.alive and wall.check_collision(tank_rect):
                    # 计算重叠面积
                    overlap_rect = tank_rect.clip(wall.rect)
                    overlap_area = overlap_rect.width * overlap_rect.height
                    grass_overlap += overlap_area
        
        # 计算坦克总面积
        tank_area = self.size * self.size
        
        # 如果草丛重叠面积超过坦克面积的四分之一，则激活隐藏效果
        if grass_overlap >= tank_area * 0.25:
            self.in_grass = True
        else:
            self.in_grass = False
            
        self.stealth_mode = self.in_grass

    def draw(self, surface, camera_x=0, camera_y=0):  # 绘制坦克
        if not self.live:
            return
            
        # 转换坐标到屏幕坐标
        screen_x = self.x - camera_x
        screen_y = self.y - camera_y
        
        # 只绘制在可视区域内的坦克
        if -self.size <= screen_x <= 864 and -self.size <= screen_y <= 864:
            # 如果在草丛中且是敌人，则不绘制（隐身效果）
            if self.stealth_mode and not self.is_player:
                return
                
            # 绘制护盾
            if self.shield_active:
                shield_radius = self.size // 2 + 5
                shield_alpha = 150
                shield_surface = pygame.Surface((shield_radius * 2, shield_radius * 2), pygame.SRCALPHA)
                pygame.draw.circle(shield_surface, (255, 255, 100, shield_alpha), (shield_radius, shield_radius), shield_radius, 3)
                surface.blit(shield_surface, (screen_x + self.size//2 - shield_radius, screen_y + self.size//2 - shield_radius))
            
            # 绘制坦克主体
            if self.hit_flash > 0:  # 受击闪烁
                flash_color = (255, 255, 0) if self.hit_flash % 2 == 0 else self.color
                pygame.draw.rect(surface, flash_color, (screen_x, screen_y, self.size, self.size))
                self.hit_flash -= 1
            else:
                # 如果在草丛中，使用半透明效果
                if self.stealth_mode:
                    tank_surface = pygame.Surface((self.size, self.size), pygame.SRCALPHA)
                    pygame.draw.rect(tank_surface, (*self.color, 128), (0, 0, self.size, self.size))
                    surface.blit(tank_surface, (screen_x, screen_y))
                else:
                    pygame.draw.rect(surface, self.color, (screen_x, screen_y, self.size, self.size))
            
            # 绘制炮管
            if self.direction == 'UP':
                pygame.draw.rect(surface, (0, 0, 0), (screen_x + self.size//2 - 3, screen_y - 15, 6, 15))
            elif self.direction == 'DOWN':
                pygame.draw.rect(surface, (0, 0, 0), (screen_x + self.size//2 - 3, screen_y + self.size, 6, 15))
            elif self.direction == 'LEFT':
                pygame.draw.rect(surface, (0, 0, 0), (screen_x - 15, screen_y + self.size//2 - 3, 15, 6))
            elif self.direction == 'RIGHT':
                pygame.draw.rect(surface, (0, 0, 0), (screen_x + self.size, screen_y + self.size//2 - 3, 15, 6))
            
            # 绘制血条
            self.draw_health_bar(surface, screen_x, screen_y)

    def move(self, keys=None, total_map_size=64, cell_size=36):  # 坦克移动
        if not self.live:
            return
        if self.shield_active:
            self.shield_time -= 16
            if self.shield_time <= 0:
                self.shield_active = False
                self.shield_time = 0
        old_x, old_y = self.x, self.y  # 保存原始位置
        if self.is_player and keys:
            if keys[pygame.K_UP]:
                self.direction = 'UP'
                self.y -= self.speed
            elif keys[pygame.K_DOWN]:
                self.direction = 'DOWN'
                self.y += self.speed
            elif keys[pygame.K_LEFT]:
                self.direction = 'LEFT'
                self.x -= self.speed
            elif keys[pygame.K_RIGHT]:
                self.direction = 'RIGHT'
                self.x += self.speed
            # 边界检查 - 适应64x64地图
            self.x = max(0, min(total_map_size * cell_size - self.size, self.x))
            self.y = max(0, min(total_map_size * cell_size - self.size, self.y))
        elif not self.is_player:
            if random.randint(0, 100) < 3:
                self.direction = random.choice(['UP', 'DOWN', 'LEFT', 'RIGHT'])
            if self.direction == 'UP':
                self.y -= self.speed
            elif self.direction == 'DOWN':
                self.y += self.speed
            elif self.direction == 'LEFT':
                self.x -= self.speed
            elif self.direction == 'RIGHT':
                self.x += self.speed
            # 敌人边界检查 - 适应64x64地图
            if self.x <= 0 or self.x >= total_map_size * cell_size - self.size:
                self.direction = 'LEFT' if self.direction == 'RIGHT' else 'RIGHT'
            if self.y <= 0 or self.y >= total_map_size * cell_size - self.size:
                self.direction = 'UP' if self.direction == 'DOWN' else 'DOWN'
        tank_rect = pygame.Rect(self.x, self.y, self.size, self.size)
        if self.game_state and self.game_state.walls:
            for wall in self.game_state.walls:
                if wall.alive and wall.wall_type != 2 and wall.check_collision(tank_rect):  # 草丛不阻挡移动
                    self.x, self.y = old_x, old_y
                    break
        
        # 检查草丛碰撞
        self.check_grass_collision()

    def fire(self):  # 发射子弹
        if not self.live:
            return
        if self.direction == 'UP':
            bullet = Bullet(self.x + self.size//2 - 2, self.y, 0, -10, self.is_player)
        elif self.direction == 'DOWN':
            bullet = Bullet(self.x + self.size//2 - 2, self.y + self.size, 0, 10, self.is_player)
        elif self.direction == 'LEFT':
            bullet = Bullet(self.x, self.y + self.size//2 - 2, -10, 0, self.is_player)
        else:
            bullet = Bullet(self.x + self.size, self.y + self.size//2 - 2, 10, 0, self.is_player)
        self.bullets.append(bullet)

    def hit(self):  # 坦克受击
        if self.shield_active:
            return False
        self.hit_flash = 10
        self.health -= 1
        if self.health <= 0:
            self.live = False
        return True

    def activate_shield(self, duration=5000):  # 激活护盾
        self.shield_active = True
        self.shield_time = duration

    def add_health(self):  # 增加生命值
        if self.health < self.max_health:
            self.health += 1
            return True
        return False
    
    def draw_health_bar(self, surface, x, y):
        """绘制坦克血条，玩家三档，敌人一档"""
        # 血条位置（坦克头顶）
        bar_width = self.size
        bar_height = 6
        bar_x = x
        bar_y = y - 12
        
        # 血条背景（灰色）
        pygame.draw.rect(surface, (100, 100, 100), (bar_x, bar_y, bar_width, bar_height))
        
        # 计算血量百分比
        health_percent = self.health / self.max_health
        
        if self.is_player:
            # 玩家坦克：三档血条
            if health_percent > 0.66:  # 血量 > 66% - 绿色（健康）
                health_color = (0, 255, 0)  # 绿色
            elif health_percent > 0.33:  # 血量 33%-66% - 黄色（警告）
                health_color = (255, 255, 0)  # 黄色
            else:  # 血量 < 33% - 红色（危险）
                health_color = (255, 0, 0)  # 红色
            
            # 绘制血条填充
            fill_width = int(bar_width * health_percent)
            if fill_width > 0:
                pygame.draw.rect(surface, health_color, (bar_x, bar_y, fill_width, bar_height))
            
            # 绘制三档分割线
            segment_width = bar_width // 3
            for i in range(1, 3):
                line_x = bar_x + i * segment_width
                pygame.draw.line(surface, (50, 50, 50), (line_x, bar_y), (line_x, bar_y + bar_height), 1)
        else:
            # 敌人坦克：一档血条
            if self.health > 0:
                health_color = (255, 0, 0)  # 红色
                # 一档血条，一格血占满整个血条
                pygame.draw.rect(surface, health_color, (bar_x, bar_y, bar_width, bar_height))
        
        # 绘制血条边框
        pygame.draw.rect(surface, (255, 255, 255), (bar_x, bar_y, bar_width, bar_height), 1)
